using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace BardsTaleMapViewer {
  public class MonsterType {
    public static string [] _attackEffectsString = new string [] { "-", "Poison", "Drain", "Insanity (Nuts)", "Wither (Old)", "Possess", "Stone", "Critical" };
    public static string [] _hitTypesString = new string [] { "Swing/Slash", "Kick/Punch", "Claw/Tear", "Bite/Gnaw", "Stab/Slice", "Slam/Strike", "Grope/ReachToward", "Peer/Stare" };

    public int _index;
    public Beastiary _beastiary;

    public MonsterType (int index, Beastiary beastiary) {
      _index = index;
      _beastiary = beastiary;

      if (Unk != 0)
        throw new Exception ();
    }

    public string GetName (int nb) {
      if (nb > 1)
        return (NamePlural);
      else
        return (NameSingular);
    }

    public string NameSingular {
      get {
        return (Beastiary.GetSingular (_beastiary._monsterTypesName [_index]));
      }
    }

    public string NamePlural {
      get {
        return (Beastiary.GetPlural (_beastiary._monsterTypesName [_index]));
      }
    }

    private int AttackEffectAndPower {
      get {
        return (_beastiary._monsterTypesPlus1AttackEffectAndPower [_index + 1]);
      }
    }

    public int AttackEffect {
      get {
        return (AttackEffectAndPower >> 5);
      }
    }

    public string AttackEffectString {
      get {
        return (_attackEffectsString [AttackEffect]);
      }
    }

    public int Power {
      get {
        return (AttackEffectAndPower & 0x1F);
      }
    }

    public int PictureIndex {
      get {
        return (_beastiary._monsterTypesPlus1PictureIndex [_index + 1]);
      }
    }

    public int [] Actions {
      get {
        return (_beastiary._monsterTypesPlus1Actions [_index + 1]);
      }
    }

    public int HitTypeIndnex {
      get {
        return (_beastiary._monsterTypesPlus1HitTypeIndex [_index + 1]);
      }
    }

    public string HitTypeString {
      get {
        return (_hitTypesString [HitTypeIndnex]);
      }
    }

    public int Experience {
      get {
        int experience = _beastiary._monsterTypesPlus1Experience [_index + 1];
        if ((_index + 1) >= 16)
          experience <<= 8;
        return (experience);
      }
    }

    private int HpMinAndArmorClassBonus {
      get {
        return (_beastiary._monsterTypesPlus1HpMinAndArmorClassBonus [_index + 1]);
      }
    }

    public int HpMin {
      get {
        return (HpMinAndArmorClassBonus >> 4);
      }
    }

    public int ArmorClass {
      get {
        return (HpMinAndArmorClassBonus & 0x1F);
      }
    }

    private int HpSizeAndNbSize {
      get {
        return (_beastiary._monsterTypesPlus1HpSizeAndNbSize [_index + 1]);
      }
    }

    public int HpSize {
      get {
        return (HpSizeAndNbSize >> 4);
      }
    }

    public int HpMax {
      get {
        int nb = _beastiary.CalcFromSize (HpSize);
        nb += HpMin;
        if (nb > 255)
          nb = 255;
        return (nb);
      }
    }

    public int Unk {
      get {
        return ((HpSizeAndNbSize >> 3) & 0x01);
      }
    }

    public int NbSize {
      get {
        return (HpSizeAndNbSize & 0x07);
      }
    }

    public int NbMin {
      get {
        return (1);
      }
    }

    public int NbMax {
      get {
        int nb;
        if (NbSize == 0)
          nb = 0;
        else
          nb = _beastiary.CalcFromSize (NbSize);
        nb++;
        if (nb > 99)
          nb = 99;
        return (nb);
      }
    }

    public string Text {
      get {
        return (string.Format ("#{0} Power: {1} AttackEffect: {2}", _index, Power, AttackEffectString));
      }
    }

    public string GetAction (int actionIndex, bool html) {
      int action = Actions [actionIndex];
      if (action == 0) {
        return ("Attack");
      }
      if (action <= 78) {
        int spellIndex = _beastiary._actionsSpellIndex [action];
        Spell spell = _beastiary._game._spellbook._spells [spellIndex];
        //return (string.Format ("#{0}: Spell #{1}: {2}", action, spellIndex, spell.Name));
        if (!html)
          return (string.Format ("Spell #{0}: {2}", spellIndex, html ? "<br>" : " ", spell.Name));
        else
          return (string.Format ("Spell #{0}: {2}", spellIndex, html ? "<br>" : " ", html ? spell.ShortDescHtml : spell.ShortDesc));
      }
      else if ((action >= 79) && (action != 254)) {
        int spellIndex = action;
        Spell spell = _beastiary._game._spellbook._spells [spellIndex];
        //return (string.Format ("#{0}: Breath: {1}", action, spell.Name));
        //return (string.Format ("Spell #{0}:{1}Breath: {2}", spellIndex, separator, spell.Name ?? "*"));
        if (!html)
          return (string.Format ("Spell #{0}: {2}{1}{3}", spellIndex, html ? "<br>" : " ", spell.Name, html ? spell.ParmsHtml : spell.Parms));
        else
          return (string.Format ("Spell #{0}: {2}", spellIndex, html ? "<br>" : " ", html ? spell.ShortDescHtml : spell.ShortDesc));
      }
      else if (action == 254) {
        return ("Doppleganger");
      }
      else
        throw new Exception ();
    }

    public string DifficultiesString {
      get {
        return (_beastiary.GetDifficultiesString (_index + 1));
      }
    }

    public void Dump () {
      int nameLength = Game.Lengthest (_beastiary._monsterTypesName);
      int attackEffectLength = Game.Lengthest (_attackEffectsString);
      int hitTypeLength = Game.Lengthest (_hitTypesString);

      StringBuilder sb = new StringBuilder ();
      sb.AppendFormat ("{0,3}", _index);
      sb.AppendFormat ("  {0,-8}", DifficultiesString);
      sb.AppendFormat ("  {0,-" + nameLength + "}", NameSingular);
      sb.AppendFormat ("  {0,5}", Power);
      sb.AppendFormat ("  {0,3}", PictureIndex);
      sb.AppendFormat ("  [{0,2};{1,3}]", HpMin, HpMax);
      sb.AppendFormat ("  {0,2}", ArmorClass);
      sb.AppendFormat ("  [{0,1};{1,2}]", NbMin, NbMax);
      sb.AppendFormat ("  {0,14}", Dice.DiceWithMinMaxString (4, Power + 1, 0, 1, 2, 2, 3));
      sb.AppendFormat ("  {0,-" + hitTypeLength + "}", HitTypeString);
      sb.AppendFormat ("  {0,-" + attackEffectLength + "}", AttackEffectString);
      sb.AppendFormat ("  {0,4}", Experience);
      sb.AppendFormat ("  {0,3}", GetAction (0, false));
      sb.AppendFormat ("  {0,3}", GetAction (1, false));
      sb.AppendFormat ("  {0,3}", GetAction (2, false));
      sb.AppendFormat ("  {0,3}", GetAction (3, false));
      Console.WriteLine (sb.ToString ());
    }

    public StringBuilder DumpHtml () {
      int nameLength = Game.Lengthest (_beastiary._monsterTypesName);
      int attackEffectLength = Game.Lengthest (_attackEffectsString);
      int hitTypeLength = Game.Lengthest (_hitTypesString);

      StringBuilder sb = new StringBuilder ();
      sb.AppendFormat ("<tr>");
      sb.AppendFormat ("<th>{0}</th>", _index);
      sb.AppendFormat ("<th style='font-family: monospace;font-size: 13px;white-space:nowrap;'>{0}</th>", DifficultiesString);
      sb.AppendFormat ("<td>{0}</td>", NameSingular);
      sb.AppendFormat ("<th>{0}</th>", Power);
      string img = string.Format ("<img width='56' height='44' src='Images/Pictures/Bard 1 {0} Atari.gif' alt='Bard 1 {0} Atari' />", (PictureIndex + 1).ToString ().PadLeft (2, '0'));
      sb.AppendFormat ("<th>{0}</th>", img, PictureIndex);
      sb.AppendFormat ("<th style='white-space:nowrap'>[{0};{1}]</th>", HpMin, HpMax);
      sb.AppendFormat ("<th>{0}</th>", ArmorClass);
      sb.AppendFormat ("<th style='white-space:nowrap'>[{0};{1}]</th>", NbMin, NbMax);
      sb.AppendFormat ("<th style='white-space:nowrap'>{0}</th>", Dice.DiceWithMinMaxString (4, Power + 1, 0, 1, 2, 2, 3));
      sb.AppendFormat ("<th>{0}</th>", HitTypeString);
      sb.AppendFormat ("<th style='white-space:nowrap'>{0}</th>", AttackEffectString);
      sb.AppendFormat ("<th>{0}</th>", Experience);
      sb.AppendFormat ("<th style='white-space:nowrap'>{0}</th>", GetAction (0, true));
      sb.AppendFormat ("<th style='white-space:nowrap'>{0}</th>", GetAction (1, true));
      sb.AppendFormat ("<th style='white-space:nowrap'>{0}</th>", GetAction (2, true));
      sb.AppendFormat ("<th style='white-space:nowrap'>{0}</th>", GetAction (3, true));
      sb.AppendFormat ("</tr>");
      return (sb);
    }
  }
}
